#include <elf.h>
#include "fs.h"

static int check_elf(Elf32_Ehdr *e)
{
	if(e->e_ident[0] == 0x7f
		&& e->e_ident[1] == 'E'
		&& e->e_ident[2] == 'L'
		&& e->e_ident[3] == 'F'
		&& 1) // There are still many things need checking
		return 0;
	else
		return 1;
}

int load_elf(const char *path, u32_t *begin_addr)
{
	Elf32_Ehdr elf_header;
	Elf32_phdr pro_header[10], *p;
	int ret, size, fd, i;

	fd = open(path, OF_READ);
	if(fd < 0)
		return -1;

	ret = read(fd, (char *)&elf_header, sizeof(Elf32_Ehdr));
	if(ret != 0)
		return -2;
	if(check_elf(&elf_header) != 0)
		return -3;

	size = elf_header.e_phentsize * elf_header.e_phnum;
	lseek(fd, elf_header.e_phoff, SEEK_SET);
	ret = read(fd, (char *)pro_header, size);
	if(ret != 0)
		return -4;

	for(i = 0; i < elf_header.e_phnum; i++) {
		if(pro_header[i].p_type != PT_LOAD)
			continue;

		p = &pro_header[i];
		lseek(fd, p->p_offset, SEEK_SET);
		read(fd, (char *)(p->p_vaddr), p->p_filesz);

		if((size = p->p_memsz - p->p_filesz) > 0)
			memset(p->p_vaddr + p->p_filesz, 0, size);
	}

	*begin_addr = elf_header.e_entry;
	close(fd);
	return 0;
}
